package com.example.gateway.filter;


import com.example.api.service.AuthService;
import com.example.common.constant.ApiParamConsts;
import com.example.common.constant.HttpHeaders;
import com.example.common.constant.HttpStatus;
import com.example.common.entity.AccessTokenBody;
import com.example.common.exception.ErrorMsgEnum;
import com.example.common.utils.AccessTokenUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Objects;

@Slf4j
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {

    @Reference
    AuthService authService;


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //TODO
        log.info("start checking");
//        String clientIp = Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getHostString();
//        log.info(clientIp);
        String reqPath = exchange.getRequest().getURI().getPath();
        String email = exchange.getRequest().getQueryParams().getFirst(ApiParamConsts.EMAIL);
        if (reqPath.contains("/app/create")) {
            //判断是否是认证
            if (StringUtils.isEmpty(email)) {
                //email为空时，无法进行
                return FilterUtil.customError(exchange, "email为空，无法添加认证！", 1);
            } else {
                //有email时，不进行权限认证，直接进行应用授权
                return chain.filter(exchange);
            }
        } else if (reqPath.contains("access_token/get") || reqPath.contains("callback/config")) {
            //获取access_token, 配置回调直接放行
            return chain.filter(exchange);
        }
        String accessToken = exchange.getRequest().getQueryParams().getFirst(ApiParamConsts.ACCESS_TOKEN);
        if (StringUtils.isEmpty(accessToken)){
            return FilterUtil.customError(exchange, ErrorMsgEnum.CODE_41001.getMsg(), ErrorMsgEnum.CODE_41001.getCode());
        }
        AccessTokenBody tokenBody = AccessTokenUtils.decrypt(accessToken);
        if (tokenBody == null){
            return FilterUtil.customError(exchange, ErrorMsgEnum.CODE_40014.getMsg(), ErrorMsgEnum.CODE_40014.getCode());
        }
        // 优先获取新token
        String newestToken = authService.getAccessTokenNew(tokenBody.getAppId());
        if (Objects.equals(accessToken, newestToken)) {
            return nextFilter(exchange, chain, tokenBody);
        }
        String oldToken = authService.getAccessTokenOld(tokenBody.getAppId());
        if (Objects.equals(accessToken, oldToken)) {
            return nextFilter(exchange, chain, tokenBody);
        }
        exchange.getResponse().setStatusCode(org.springframework.http.HttpStatus.valueOf(HttpStatus.NON_AUTHORITATIVE_INFORMATION));
        return FilterUtil.customError(exchange, ErrorMsgEnum.CODE_42001.getMsg(), ErrorMsgEnum.CODE_42001.getCode());
    }

    private Mono<Void> nextFilter(ServerWebExchange exchange, GatewayFilterChain chain, AccessTokenBody tokenBody) {
        ServerHttpRequest request = exchange.getRequest().mutate()
                .header(HttpHeaders.TENANT_ID, tokenBody.getTenantId())
                .header(HttpHeaders.APP_ID, tokenBody.getAppId())
                .build();
        return chain.filter(exchange.mutate().request(request).build());
    }

    /**
     * 过滤器优先级，越低越高
     *
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}
